import json
import re
from django import http
from django.contrib.auth import login
from django.db import DatabaseError
from django.views import View
from django_redis import get_redis_connection
from django.shortcuts import render
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
# Create your views here.
import logging

from carts.utils import merge_cart_cookie_to_redis
from meiduo_mall.utils.secret import SecretOauth
from oauth.models import OAuthQQUser
from users.models import User

logger = logging.getLogger('django')


class QQURLView(View):

    def get(self, request):
        # next 记录登录成功后跳转到的页面
        _next = request.GET.get('next')

        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        # 额外的参数，在三方交互中全程携带。通常使用该参数来指定用户登录成功之后，跳转会的用户页面
                        state=_next
                        )

        # 获取qq地址
        login_url = oauth.get_qq_url()

        return http.JsonResponse({
            'code': 0,
            'errmsg': 'ok',
            'login_url': login_url
        })


class QQUserView(View):
    def get(self, request):
        code = request.GET.get('code')

        if not code:
            return http.JsonResponse({
                'code': 400,
                'errmsg': '缺少code参数',
            })

        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=None
                        )

        try:
            # 调用对象的方法, 根据 code 获取 access_token:
            access_token = oauth.get_access_token(code)
            # 携带access_token 向qq服务器，请求openid
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({
                'code': 400,
                'errmsg': 'oauth2.0认证失败，获取qq信息失败'
            })

        # 绑定openid
        try:
            oauth_qq = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            access_token = SecretOauth().dumps({'openid': openid})
            return http.JsonResponse({
                'code': 300,
                'errmsg': 'ok',
                'access_token': access_token
            })
        else:
            user = oauth_qq.user
            login(request, user)
            response = http.JsonResponse({
                'code': 0,
                'errmsg': 'ok'
            })
            return response

    def post(self, request):
        # 接收参数
        data_dict = json.loads(request.body.decode())

        mobile = data_dict.get('mobile')
        password = data_dict.get('password')
        sms_code = data_dict.get('sms_code')
        access_token = data_dict.get('access_token')

        # 参数必要性校验
        if not all([mobile, password, sms_code, access_token]):
            return http.JsonResponse({
                'code': 400,
                'errmsg': '缺少必要参数'
            })

        # 校验手机号
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({
                'code': 400,
                'errmsg': '手机号格式错误'
            })

        # 校验密码
        if not re.match(r'^[a-zA-Z0-9_-]{8,20}$', password):
            return http.JsonResponse({
                'code': 400,
                'errmsg': 'password格式错误'
            })

        # 短信验证码
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get(f'sms_{mobile}')

        # 先执行判断是否为空
        if sms_code_server is None:
            return http.JsonResponse({
                'code': 400,
                'errmsg': '短信验证码失效'
            })

        if sms_code != sms_code_server.decode():
            return http.JsonResponse({
                'code': 400,
                'errmsg': '短信验证码输入有误'
            })

        # 业务处理--绑定账号
        data_id = SecretOauth().loads(access_token).get('openid')
        if not data_id:
            return http.JsonResponse({
                'code': 400,
                'errmsg': '缺少openid'
            })

        # 根据用户传递的手机号查询数据
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        else:
            # 用户存在，校验用户密码
            if not user.check_password(password):
                return http.JsonResponse({
                    'code': 400,
                    'errmsg': '密码输入有误'
                })
        # 将用户绑定openid
        try:
            OAuthQQUser.objects.create(openid=data_id,
                                       user=user)
        except DatabaseError:
            return http.JsonResponse({
                'code': 400,
                'errmsg': '往数据库添加数据错误'
            })

        # 状态保持
        login(request, user)

        # 创建响应对象
        response = http.JsonResponse({
            'code': 0,
            'errmsg': 'ok'
        })

        # 登录时将用户名写入cookie
        response.set_cookie('username', user.username, max_age=3600 * 24 * 14)

        # TODO:合并购物车
        merge_cart_cookie_to_redis(request=request, response=response)

        return response